home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
lisp
/
kcl
/
akcl
/
akcl1615.lha
/
misc
/
cstruct.lsp
next >
Wrap
Lisp/Scheme
|
1991-03-18
|
5KB
|
158 lines
;; Sample usage: Create lisp defstructs corresponding to C structures:
(use-package "SLOOP")
;; How to: Create a file foo.c which contains just structures
;; and possibly some externs.
;; cc -E /tmp/foo1.c > /tmp/fo2.c
;; ../xbin/strip-ifdef /tmp/fo2.c > /tmp/fo3.c
;; then (parse-file "/tmp/fo3.c")
;; will return a list of defstructs and appropriate slot offsets.
(defun white-space (ch) (member ch '(#\space #\linefeed #\return #\newline #\tab)))
(defvar *eof* (code-char 255))
(defun delimiter(ch) (or (white-space ch)
(member ch '(#\, #\; #\{ #\} #\*))))
(defun next-char (st)
(let ((char (read-char st nil *eof*)))
(case char
(#\{ char)
(
#\/ (cond ((eql (peek-char nil st nil) #\*)
(read-char st)
(sloop when (eql (read-char st) #\*)
do (cond ((eql (read-char st) #\/ )
(return-from next-char (next-char st))))))
(t char)))
((#\tab #\linefeed #\return #\newline )
(cond ((member (peek-char nil st nil) '(#\space #\tab #\linefeed #\return #\newline ))
(return-from next-char (next-char st))))
#\space)
(t char))))
(defun get-token (st &aux tem)
(sloop while (white-space (peek-char nil st nil))
do (read-char st))
(cond ((member (setq tem (peek-char nil st nil)) '(#\, #\; #\* #\{ #\} ))
(return-from get-token (coerce (list (next-char st)) 'string))))
(sloop with x = (make-array 10 :element-type 'character :fill-pointer 0
:adjustable t)
when (delimiter (setq tem (next-char st)))
do (cond ((> (length x) 0)
(or (white-space tem) (unread-char tem st))
(return x)))
else
do
(cond ((eql tem *eof*) (return *eof*))
(t (vector-push-extend tem x)))))
(defvar *parse-list* nil)
(defvar *structs* nil)
(defun parse-file (fi &optional *structs*)
(with-open-file (st fi)
(let ((*parse-list*
(sloop while (not (eql *eof* (setq tem (get-token st))))
collect (intern tem))))
(print *parse-list*)
(let ((structs
(sloop while (setq tem (parse-struct))
do (push tem *structs*)
collect tem)))
(get-sizes fi structs)
(with-open-file (st "gaz3.lsp")
(prog1
(list structs (read st))
(delete-file "gaz3.lsp")))))))
(defparameter *type-alist* '((|short| . signed-short)
(|unsigned short| . unsigned-short)
(|char| . signed-char)
(|unsigned char| . unsigned-char)
(|int| . fixnum)
(|long| . fixnum)
(|object| . t)))
(defun parse-type( &aux top)
(setq top (pop *parse-list*))
(cond ((member top '(|unsigned| |signed|))
(push (intern (format nil "~a-~a" (pop *parse-list*))) *parse-list*)
(parse-type))
((eq '* (car *parse-list*)) (pop *parse-list*) 'fixnum)
((eq top '|struct|)
(prog1
(cond ((car (member (car *parse-list*) *STRUCTS* :key 'cadr)))
(t (error "unknown struct ~a " (car *parse-list*))))
(pop *parse-list*)
))
((cdr (assoc top *type-alist*)))
(t (error "unknown type ~a " top))))
(defun expect (x) (or (eql (car *parse-list*) x)
(error "expected ~a at beginning of ~s" x *parse-list*))
(pop *parse-list*))
(defun parse-field ( &aux tem)
(cond ((eql (car *parse-list*) '|}|)
(pop *parse-list*)
(expect '|;|)
nil)
(t
(let ((type (parse-type)))
(sloop until (eql (setq tem (pop *parse-list*)) '|;|)
append (get-field tem type)
do (or (eq (car *parse-list*) '|;|) (expect '|,|)))))))
(deftype pointer () `(integer ,most-negative-fixnum most-positive-fixnum))
(defun get-field (name type)
(cond ((eq name '|*|)(get-field (pop *parse-list*) 'pointer))
((and (consp type) (eq (car type) 'defstruct))
(sloop for w in (cddr type)
append (get-field
(intern (format nil "~a.~a" name (car w)))
(fourth w))))
(t
`((,name ,(if (eq type t) nil 0) :type ,type)))))
(defun parse-struct ()
(cond ((null *parse-list*) (return-from parse-struct nil)))
(cond ((not (eq (car *parse-list*) '|struct|))
(sloop until (eq (pop *parse-list*) '|;|))
(return-from parse-struct (parse-struct))))
(expect '|struct|)
(let* ((name (prog1 (pop *parse-list*)(expect '|{|))))
`(defstruct ,name ,@
(sloop while (setq tem (parse-field))
append tem))))
(defun printf (st x &rest y)
(format st "~%printf(\"~a\"" x)
(sloop for w in y do (princ "," st) (princ y st))
(princ ");" st))
(defun get-sizes (file structs)
(with-open-file (st "gaz0" :direction :output)
(sloop for i from 1
for u in structs
do (format st "struct ~a SSS~a;~%" (second u) i))
(format st "~%main() {~%")
(printf st "(")
(sloop for i from 1
for u in structs
do
(printf st (format nil "(|~a| " (second u)))
(sloop for w in (cddr u)
do
(printf st " %d "
(format nil "(char *)&SSS~a.~a - (char *)&SSS~a"
i (car w) i)))
(printf st ")"))
(printf st ")")
(princ " ;}" st))
(system
(format nil "cat ~a gaz0 > tmpx.c ; cc tmpx.c -o tmpx ; (tmpx > gaz3.lsp) ; rm -f gaz0" file)))